package org.atlantis.netty.http;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpChunkTrailer;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;

public class HttpRequestHandler extends SimpleChannelUpstreamHandler {

	private HttpRequest request;
	private boolean readingChunks;
	// 缓存储存response内容
	private final StringBuilder buf = new StringBuilder();

	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
		if (!readingChunks) {
			HttpRequest request = this.request = (HttpRequest) e.getMessage();
			if (HttpHeaders.is100ContinueExpected(request)) {
				send100Continue(e);
			}

			buf.setLength(0);
			buf.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
			buf.append("===================================\r\n");
			buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
			buf.append("HOSTNAME: " + HttpHeaders.getHost(request, "unknow") + "\r\n");
			buf.append("REQUEST URI: " + request.getUri() + "\r\n\r\n");

			for (Map.Entry<String, String> header : request.getHeaders()) {
				buf.append("HEADER: " + header.getKey() + "=" + header.getValue() + "\r\n");
			}
			buf.append("\r\n");

			QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
			Map<String, List<String>> params = queryStringDecoder.getParameters();
			for (Entry<String, List<String>> param : params.entrySet()) {
				String key = param.getKey();
				List<String> vals = param.getValue();
				for (String val : vals)
					buf.append("PARAM: " + key + "=" + val + "\r\n");
			}
			buf.append("\r\n");
			if (request.isChunked()) readingChunks = true;
			else {
				ChannelBuffer content = request.getContent();
				if (content.readable()) buf.append("CONTENT: " + content.toString(CharsetUtil.UTF_8));
				writeResponse(e);
			}
		} else {
			HttpChunk chunk = (HttpChunk) e.getMessage();
			if (chunk.isLast()) {
				readingChunks = false;
				buf.append("end of content\r\n");
				HttpChunkTrailer trailer = (HttpChunkTrailer) chunk;
				if (!trailer.getHeaderNames().isEmpty()) {
					buf.append("\r\n");
					for (String name : trailer.getHeaderNames()) {
						for (String value : trailer.getHeaders(name)) {
							buf.append("TRAILING HEADDER: " + name + "=" + value + "\r\n");
						}
					}
					buf.append("\r\n");
				}
				writeResponse(e);
			} else {
				buf.append("CHUNK: " + chunk.getContent().toString(CharsetUtil.UTF_8));
			}
		}
	}

	private void writeResponse(MessageEvent e) {
		// 判断是否需要关闭连接
		boolean keepAlive = HttpHeaders.isKeepAlive(request);
		// 构建Response对象
		HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
		response.setContent(ChannelBuffers.copiedBuffer(buf.toString(), CharsetUtil.UTF_8));
		response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
		if (keepAlive) response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, response.getContent().readableBytes());

		// 对Cookie信息进行编码
		String cookieString = request.getHeader(HttpHeaders.Names.COOKIE);
		if (cookieString != null) {
			CookieDecoder cookieDecoder = new CookieDecoder();
			Set<Cookie> cookies = cookieDecoder.decode(cookieString);
			if (!cookies.isEmpty()) {
				CookieEncoder cookieEncoder = new CookieEncoder(true);
				for (Cookie cookie : cookies)
					cookieEncoder.addCookie(cookie);
				response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
			}
		}

		// 将response返回
		ChannelFuture future = e.getChannel().write(response);
		if (!keepAlive) {
			future.addListener(ChannelFutureListener.CLOSE);
		}
	}

	private void send100Continue(MessageEvent e) {
		HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
		e.getChannel().write(response);
	}
}
